package com.backend.service.blog.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import com.backend.mapper.blog.ArticleMapper;
import com.backend.service.blog.ArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.constant.RedisConstant;
import com.common.exception.ArticleException;
import com.common.threadlocal.UserLocal;
import com.pojo.dto.AddArticleDTO;
import com.pojo.dto.UserDTO;
import com.pojo.entity.Article;
import com.pojo.vo.ArticleVO;
import io.jsonwebtoken.lang.Collections;
import jodd.util.ArraysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    ArticleMapper articleMapper;
    @Override
    @Transactional
    public Integer addArticle(AddArticleDTO addArticleDTO) {
        String content = addArticleDTO.getContent();
        String title = addArticleDTO.getTitle();
        Article article = new Article();
        article.setTitle(title);
        article.setUpdateDatetime(LocalDateTime.now());
        article.setCreateDatetime(LocalDateTime.now());
        UserDTO userDTO = UserLocal.getCurrentUserDTO();
        article.setUserId(userDTO.getId());
        article.setSummary(addArticleDTO.getSummary());
        Long result1 = articleMapper.addArticle(article);
        if (result1.equals(0L)) {
            throw new ArticleException("文章添加失败");
        }
        Long id = article.getId();
        Integer result = articleMapper.saveContent(content, id);
        return result;
    }

    @Override
    @Transactional
    public Integer removeArticle(Long id) {
        Integer result1 = articleMapper.removeArticle(id);
        if (result1 == 0) {
            throw new ArticleException("文章删除失败");
        }
        Integer result2 = articleMapper.removeContent(id);
        if (result2 == 0) {
            throw new ArticleException("文章删除失败");
        }
        return 1;
    }

    @Override
    @Transactional
    public Integer updateArticle(Long id, AddArticleDTO addArticleDTO) {
        Article article = BeanUtil.copyProperties(addArticleDTO, Article.class);
        article.setUpdateDatetime(LocalDateTime.now());
        article.setId(id);
        Integer result = articleMapper.updateArticle(article);
        if (result == 0) {
            throw new ArticleException("文章更新失败");
        }
        Integer result1 =articleMapper.updateContent(id, addArticleDTO.getContent());
        if (result1 == 0) {
            throw new ArticleException("文章更新失败");
        }
        return result;
    }

    @Override
    public ArticleVO getArticleById(Long id) {
        Article article = articleMapper.selectById(id);
        if (article == null) {
            throw new ArticleException("文章不存在");
        }
        ArticleVO articleVO = BeanUtil.copyProperties(article, ArticleVO.class);
        String content = articleMapper.getContent(id);
        articleVO.setContent(content);
        return articleVO;
    }

    @Override
    public List<ArticleVO> getArticles(Long id) {
        List<Long> articleIds = articleMapper.getAllArticleIdByUserId(id);
        List<ArticleVO> articleVOS = articleIds.stream().map(articleId -> {
            return getArticleById(articleId);
        }).collect(Collectors.toList());
        return articleVOS;
    }

    @Override
    @Transactional
    public Integer likeArticle(Long id) {
        UserDTO userDTO = UserLocal.getCurrentUserDTO();
        Long userId = userDTO.getId();
        String key = "blog:like:" + id;
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        if (score == null) {
            boolean isSuccess = update().setSql("poll_count = poll_count + 1").eq("id", id).update();
            if (isSuccess) {
                LocalDateTime now = LocalDateTime.now();
                Integer result = articleMapper.addPoll(now, id, userId);
                if (result == 0) {
                    throw new ArticleException("点赞添加错误");
                }
                stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());
            }
        } else {
            boolean isSuccess = update().setSql("poll_count = poll_count - 1").eq("id", id).update();
            if (isSuccess) {
                Integer result = articleMapper.removePoll(id, userId);
                if (result == 0) {
                    throw new ArticleException("点赞删除错误");
                }
                stringRedisTemplate.opsForZSet().remove(key, userId.toString());
            }
        }
        return 1;
    }

    @Override
    @Transactional
    public Integer setEssence(Long id) {
        UserDTO userDTO = UserLocal.getCurrentUserDTO();
        Long userId = userDTO.getId();
        String key = RedisConstant.BLOG_ESSENCE_KEY + id;
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        if (score == null) {
            boolean isSuccess = update().setSql("is_essence = 1").eq("id", id).update();
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());
            } else {
                return 0;
            }
        } else {
            boolean isSuccess = update().setSql("is_essence = 0").eq("id", id).update();
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().remove(key, userId.toString());
            } else {
                return 0;
            }
        }
        return 1;
    }

    @Override
    public Integer setTop(Long id) {
        UserDTO userDTO = UserLocal.getCurrentUserDTO();
        Long userId = userDTO.getId();
        String key = RedisConstant.BLOG_TOP_KEY + id;
        Double score = stringRedisTemplate.opsForZSet().score(key, userId.toString());
        if (score == null) {
            boolean isSuccess = update().setSql("is_top = 1").eq("id", id).update();
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().add(key, userId.toString(), System.currentTimeMillis());
            } else {
                return 0;
            }
        } else {
            boolean isSuccess = update().setSql("is_top = 0").eq("id", id).update();
            if (isSuccess) {
                stringRedisTemplate.opsForZSet().remove(key, userId.toString());
            } else {
                return 0;
            }
        }
        return 1;
    }
}
